package org.yong.springbootcmd.util;

import org.apache.commons.lang3.time.DateUtils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * 日期工具类
 *
 * @author yong2
 */
public abstract class DateUtil extends DateUtils {

  private static final DateUtil SINGLETON = new DateUtil() {};

  /**
   * 格式化当前时间
   *
   * @param pattern 格式化规则
   * @return 日期格式化字符串
   */
  public static String formatNow(String pattern) {
    return format(new Date(), pattern);
  }

  /**
   * 日期格式化
   *
   * @param date 日期
   * @param pattern 格式化规则
   * @return 日期格式化字符串
   */
  public static String format(Date date, String pattern) {
    DateFormat dateFormat = new SimpleDateFormat(pattern);
    return dateFormat.format(date);
  }

  /**
   * 解析日期字符串
   *
   * @param dateStr 日期字符串
   * @param pattern 格式化规则
   * @return 日期对象
   */
  public static Date parse(String dateStr, String pattern) {
    try {
      DateFormat dateFormat = new SimpleDateFormat(pattern);
      return dateFormat.parse(dateStr);
    } catch (ParseException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * 获取日期信息
   *
   * @param date 指定日期
   * @return 日期信息
   */
  public static DateInfo getDateInfo(Date date) {
    return SINGLETON.new DateInfo(date);
  }

  /**
   * 指定日期是否不在某个范围内
   *
   * @param date 指定日期
   * @param begin 开始时间
   * @param end 结束时间
   * @return true-不在范围内, false-在范围内
   */
  public static boolean inNotRange(Date date, Date begin, Date end) {
    return !inRange(date, begin, end);
  }

  /**
   * 指定日期是否在范围内
   *
   * @param date 指定日期
   * @param begin 开始时间
   * @param end 结束时间
   * @return true-在范围内, false-不在范围内
   */
  private static boolean inRange(Date date, Date begin, Date end) {
    long ms = date.getTime();
    return begin.getTime() <= ms && ms <= end.getTime();
  }

  /** @see #getDay(Date) */
  public static Date getDay() {
    return getDay(new Date());
  }

  /**
   * 获取日期, 不包含时间
   *
   * @param src 目标日期
   * @return 不包含时间的日期对象
   */
  public static Date getDay(Date src) {
    String pattern = "yyyy-MM-dd";
    String format = format(src, pattern);
    return parse(format, pattern);
  }

  /** 日期信息 */
  public class DateInfo {
    private Date baseDate;
    private Calendar calendar;
    public final Weekday WEEKDAY;

    private DateInfo(Date date) {
      this.baseDate = date;
      this.calendar = Calendar.getInstance();
      this.calendar.setTime(this.baseDate);
      this.WEEKDAY = new Weekday(this.calendar);
    }

    public Calendar getCalendar() {
      Calendar c = Calendar.getInstance();
      c.setTime(this.baseDate);
      return c;
    }
  }

  /** 一周每天的日期 */
  public class Weekday {
    private Calendar calendar;
    public final Date MONDAY;
    public final Date TUESDAY;
    public final Date WEDNESDAY;
    public final Date THURSDAY;
    public final Date FRIDAY;
    public final Date SATURDAY;
    public final Date SUNDAY;

    public Weekday(Calendar calendar) {
      String fmt = DateUtil.format(calendar.getTime(), "yyyy-MM-dd");
      this.calendar = Calendar.getInstance();
      this.calendar.setTime(parse(fmt, "yyyy-MM-dd"));

      final int MAX_WEEKDAY = 7;
      int weekday = this.calendar.get(Calendar.DAY_OF_WEEK);
      // 星期天=1, 星期六=7
      // 修复后
      // 星期天=0, 星期六=6
      weekday -= 1;
      if (0 == weekday) weekday = MAX_WEEKDAY;
      Date date = this.calendar.getTime();

      // Monday = 0
      // 需要加1天偏移量
      int offset = MAX_WEEKDAY - weekday;
      this.SUNDAY = addDays(date, offset);
      this.SATURDAY = addDays(this.SUNDAY, -1);
      this.FRIDAY = addDays(this.SATURDAY, -1);
      this.THURSDAY = addDays(this.FRIDAY, -1);
      this.WEDNESDAY = addDays(this.THURSDAY, -1);
      this.TUESDAY = addDays(this.WEDNESDAY, -1);
      this.MONDAY = addDays(this.TUESDAY, -1);
    }
  }
}
